#ifndef __MENURENDER3DMODELMGR_H__
#define __MENURENDER3DMODELMGR_H__

#include "IGameFramework.h"

#define MENURENDER3DMODELMGR_DOLIGHTS             1

class CMenuRender3DModelMgr : public IGameFrameworkListener, IInputEventListener
{
	public:
	// Public data definitions (enums, typedefs, structures)
	enum
	{
		kAddedModelIndex_MaxEntities = 10,
		kAddedModelIndex_Invalid = 255
	};

	typedef uint8 TAddedModelIndex;

	struct SSettings
	{
		Vec4 m_ambientLight;
		float m_imageCentreX, m_imageCentreY, m_imageWidth, m_imageHeight, m_fadeInSpeed;
		Ang3 m_entityRot;
		Vec3 m_entityBasePosition;
		Vec3 m_lightOrbitPosition;
		Ang3 m_entityContinuousRot;
		float m_lightSpecularMult, m_lightOrbitDistance, m_lightColourRed, m_lightColourGreen, m_lightColourBlue;
		float m_screenDepth, m_fovScale, m_scaleUserRotation;
		bool m_doTextureSideways, m_doScaling;
	};

private:
	// Private data definitions (enums, typedefs, structures)
	struct SRenderSingleEntityData
	{
		EntityId m_entityId;
		uint8 m_isCharacter:1;
	};

public:
	// Public member functions
	CMenuRender3DModelMgr(SSettings settings);
	~CMenuRender3DModelMgr();

	TAddedModelIndex AddModel(const char * filename, const char * materialFilename, bool isCharacter);
	void SetAnim(const char * animName, TAddedModelIndex modelIndex, float speedMultiplier = 1.0f, int layer = 0);
	void AttachToCharacter(TAddedModelIndex parentIndex, TAddedModelIndex childIndex, const char * attachHere);
	void AttachToStaticObject(TAddedModelIndex parentIndex, TAddedModelIndex childIndex, const char * mountPointName);
	ITexture* GetTexture() {return m_useTexture;}
	static void Release(bool immediateDelete = false);

	ILINE static CMenuRender3DModelMgr * GetInstance()
	{
		return s_instance;
	}

private:
	// Private member variables
	// Statics
	static CMenuRender3DModelMgr * s_instance;
	static CMenuRender3DModelMgr * s_firstNonFreedModelMgr;
	static float s_lightRotate;
	static uint8 s_numActualInstances;
	
	// Included structures etc.
	SSettings m_settings;
	SRenderSingleEntityData m_renderEntityData[kAddedModelIndex_MaxEntities];
	Vec3 m_scaleVector;

	Ang3 m_entityCurrentRotation;

	// Pointers (and things the size of a pointer)
	CMenuRender3DModelMgr * m_nextNonFreedModelMgr;
	CMenuRender3DModelMgr * m_prevNonFreedModelMgr;
	ITexture * m_useTexture;
#if MENURENDER3DMODELMGR_DOLIGHTS
	ILightSource * m_lightSource;
#endif
	float m_alpha, m_fractionPushedBackwardsBecauseOfWarning;
	
	// uint8
	TAddedModelIndex m_numRenderEntities;
	uint8 m_framesUntilReadyToAppear;
	uint8 m_framesUntilDestroy;
	uint8 m_settingsIndex;

	// Single bits
	uint8 m_releaseMe:1;

	// Our own private functionality
#if MENURENDER3DMODELMGR_DOLIGHTS
	void UpdateLightSettings(const float dt);
#endif

	void RealignAllEntitiesWithCamera();
	void SetVisibilityOfAllEntities(bool visible);
	
	// Pure virtual things in IGameFrameworkListener
	void OnPostUpdate(float dt);
	void OnLoadGame(ILoadGame* pLoadGame) {}
	void OnSaveGame(ISaveGame* pSaveGame) {}
	void OnLevelEnd(const char* nextLevel) {}
	void OnActionEvent(const SActionEvent& event) {}
	void OnPreRender();

	// Pure virtual things in IInputEventListener
	bool OnInputEvent(const SInputEvent & event) { return false; }
	int GetPriority() const { return 2; } // Need priority to be ahead of FlashFrontEnd.h which uses 1
};

#endif
